/**
 * FileName: LoginServiceImpl
 * Author: Mr.Wang
 * Date: 2025/10/15 13:45
 * Description:
 * History:
 */
package org.test.device.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.test.device.config.jwt.JwtUtils;
import org.test.device.enty.SysUser;
import org.test.device.mapper.SysUserMapper;
import org.test.device.params.RefreshTokenParam;
import org.test.device.service.LoginService;
import org.test.device.utils.ResultData;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * 〈一句话功能简述〉<br>
 * 〈〉
 *
 * @author Mr.Wang
 * @create 2025/10/15
 * @since 1.0.0
 */
@Slf4j
@Service
public class LoginServiceImpl implements LoginService {

    @Autowired
    SysUserMapper sysUserMapper;

    @Autowired
    JwtUtils jwtUtils;

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    // 注入Refresh Token的Redis键前缀
    @Value("${jwt.refresh.redis-key-prefix}")
    private String refreshTokenRedisPrefix;
    @Value("${jwt.refresh.expire-time}")
    private long refreshExpireTime;

    /**
    * @Author Mr.Wang
    * @Description 登录接口
    * @Date  2025/10/17
    * @Param username 用户名
    * @Param password 密码
    **/
    @Override
    public  ResultData login(String username, String password) {
        // 1. 校验用户名和密码是否为空
        if (username == null || password == null) {
            return new ResultData("用户名或密码不能为空");
        }

        // 2. 查询用户是否存在（根据用户名和密码查询）
        SysUser user = sysUserMapper.selectOne(
                new LambdaQueryWrapper<SysUser>()
                        .eq(SysUser::getUsername, username)
                        .eq(SysUser::getPassword, password) // 注意：真实环境需加密密码！
        );

        if (user == null) {
            return  new ResultData("账号或密码错误");
        }

        // 生成Access Token和Refresh Token
        String accessToken = jwtUtils.generateAccessToken(user.getId(),null);
        String refreshToken = jwtUtils.generateRefreshToken(user.getId());

        String redisKey = refreshTokenRedisPrefix + user.getId()+":"+user.getUsername();
        stringRedisTemplate.opsForValue().set(
                redisKey,
                refreshToken,
                refreshExpireTime,
                TimeUnit.MILLISECONDS // 与配置文件的时间单位一致
        );
        // 6. 返回双Token给前端
        Map<String, Object> tokenMap = new HashMap<>();
        tokenMap.put("accessToken", accessToken);
        tokenMap.put("refreshToken", refreshToken);
        return  new ResultData("登录成功", tokenMap);
    }

    /**
    * @Author Mr.Wang
    * @Description 刷新token接口
    * @Date  2025/10/17
    * @Param param 刷新token参数
    **/
    @Override
    public  ResultData refreshToken(RefreshTokenParam param) {
        String refreshToken = param.getRefreshToken();
        if (refreshToken == null) {
            return new ResultData("Refresh Token不能为空");
        }

        //验证Refresh Token格式与过期时间
        if (!jwtUtils.validateRefreshToken(refreshToken)) {
            return new ResultData("Refresh Token无效或已过期");
        }

        //解析Refresh Token获取用户ID
        Long userId = jwtUtils.getUserIdFromRefreshToken(refreshToken);

        //从Redis查询该用户的Refresh Token（验证是否匹配，防止伪造）
        String redisKey = refreshTokenRedisPrefix + userId;
        String redisRefreshToken = stringRedisTemplate.opsForValue().get(redisKey);
        if (redisRefreshToken == null || !redisRefreshToken.equals(refreshToken)) {
            return new ResultData("Refresh Token已失效，请重新登录");
        }

        //查询用户信息（生成新的Access Token需要角色）
        SysUser user = sysUserMapper.selectById(userId);
        if (user == null) {
            return new ResultData("用户不存在");
        }

        //生成新的Access Token（Refresh Token可选择续期，此处简化为不续期）
        String newAccessToken = jwtUtils.generateAccessToken(userId, null);
        Map<String, Object> tokenMap = new HashMap<>();
        tokenMap.put("accessToken", newAccessToken);

        return new ResultData("Access Token刷新成功", tokenMap);
    }

    /**
    * @Author Mr.Wang
    * @Description 退出登录接口
    * @Date  2025/10/17
    * @Param userId 用户ID
    **/
    @Override
    public ResultData logout(Long userId) {
        // userId可从拦截器的ThreadLocal中获取，此处简化
        String redisKey = refreshTokenRedisPrefix + userId;
        // 删除Redis中的Refresh Token
        stringRedisTemplate.delete(redisKey);
        return new ResultData("退出登录成功");
    }
}